using System;
using System.Runtime.InteropServices;

public sealed class Program {
   public static void Main() {
      // Passing 0 causes infrequent GCs
      MemoryPressureDemo(0);

      // Passing 10MB causes frequent GCs
      MemoryPressureDemo(10 * 1024 * 1024);

      // Handle Collector 
      HandleCollectorDemo();
   }

   private static void MemoryPressureDemo(Int32 size) {
      Console.WriteLine();
      Console.WriteLine("MemoryPressureDemo, size={0}", size);
      // Create a bunch of objects specifiying their logical size
      for (Int32 count = 0; count < 15; count++) {
         new BigNativeResource(size);
      }

      // For demo purposes, force everything to be cleaned-up
      GC.Collect();
      GC.WaitForPendingFinalizers();
   }

   private sealed class BigNativeResource {
      private Int32 m_size;

      public BigNativeResource(Int32 size) {
         m_size = size;
         if (m_size > 0) {
            // Make the GC think the object is physically bigger
            GC.AddMemoryPressure(m_size);
         }
         Console.WriteLine("BigNativeResource create.");
      }

      ~BigNativeResource() {
         if (m_size > 0) {
            // Make the GC think the object released more memory
            GC.RemoveMemoryPressure(m_size);
         }
         Console.WriteLine("BigNativeResource destroy.");
      }
   }


   private static void HandleCollectorDemo() {
      Console.WriteLine();
      Console.WriteLine("HandleCollectorDemo");
      for (Int32 count = 0; count < 10; count++) {
         new LimitedResource();
      }

      // For demo purposes, force everything to be cleaned-up
      GC.Collect();
      GC.WaitForPendingFinalizers();
   }

   private sealed class LimitedResource {
      // Create a HandleCollector telling it that collections should
      // occur when two or more of these objects exist in the heap
      private static HandleCollector s_hc = new HandleCollector("LimitedResource", 2);

      public LimitedResource() {
         // Tell HandleCollector that 1 more LimitResource object is in the heap
         s_hc.Add();
         Console.WriteLine("LimitedResource create.  Count={0}", s_hc.Count);
      }
      ~LimitedResource() {
         // Tell HandleCollector that 1 less LimitResource object is in the heap
         s_hc.Remove();
         Console.WriteLine("LimitedResource destroy. Count={0}", s_hc.Count);
      }
   }
}